package com.michaelbulava.TFS.ui.controls.connect;

import com.intellij.util.EventDispatcher;
import com.michaelbulava.TFS.jni.NativesHelper;
import com.michaelbulava.TFS.persistence.IdeaPersistenceStoreProvider;
import com.microsoft.tfs.core.util.serverlist.ServerListConfigurationEntry;
import com.microsoft.tfs.core.util.serverlist.ServerListManager;
import com.microsoft.tfs.core.util.serverlist.ServerListManagerFactory;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.net.URI;
import java.util.Iterator;
import java.util.Set;

/**
 * Created by mbulava on 6/15/2015.
 */
public class ServerListCombo extends JComboBox {
    private final ServerListComboModel model;
    private final EventDispatcher<ChangeListener> myEventDispatcher = EventDispatcher.create(ChangeListener.class);

    public ServerListCombo(){
        super();
        model = new ServerListComboModel();
        model.refresh();
        super.setRenderer(new ServerListComboRender());
        super.setModel(model);
        super.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED){
                    ServerListCombo.this.myEventDispatcher.getMulticaster().stateChanged(new ChangeEvent(this));
                }
            }
        });
    }

    public void addChangeListener(ChangeListener listener){
        myEventDispatcher.addListener(listener);
    }



   /* @Override
    public void setRenderer(ListCellRenderer listCellRenderer){
        //Ignore call to set Renderer.
    }

    @Override
    public void setModel(ComboBoxModel aModel){
        //Ignore call to set Model.
    }

    @Override
    public ComboBoxModel getModel(){
        return model;
    }*/

//    protected final void selectFirstItem(){
//        Object selection = null;
//        if (model.getSize() == 2)
//            selection = model.getElementAt(0);
//        if (selection != null)
//            model.setSelectedItem(selection);
//    }

    public final void refresh(){
        model.refresh();
    }

    public final boolean contains(ServerListConfigurationEntry item){
        return model.getIndexOf(item) >= 0;
    }

    public final boolean contains(URI serverURI){
        for(int i = 0; i < model.getSize(); i++){
            ServerListConfigurationEntry entry = (ServerListConfigurationEntry)model.getElementAt(i);
            if (entry != null && entry.getURI().equals(serverURI))
                return true;
            else if(serverURI == null && entry == null)
                return true;
        }
        return false;
    }

    public final void setSelectedServerListEntry(ServerListConfigurationEntry item){
        super.setSelectedItem(item);
    }

    public final void setSelectedServerListEntry(URI serverURI){
        for(int i = 0; i < model.getSize(); i++){
            ServerListConfigurationEntry item = (ServerListConfigurationEntry)model.getElementAt(i);
            if (item != null && item.getURI().equals(serverURI)) {
                super.setSelectedItem(item);
                return;
            } else if (item == null && serverURI == null) {
                super.setSelectedItem(item);
                return;
            }
        }
    }

    public final ServerListConfigurationEntry getSelectedServerListEntry(){
        Object value = getSelectedItem();
        if (value != null)
            return (ServerListConfigurationEntry)value;
        else
            return null;
    }

    private class ServerListComboRender extends JLabel implements ListCellRenderer{

        public ServerListComboRender(){
            setOpaque(true);
        }
        /**
         * Return a component that has been configured to display the specified value. That component's <code>paint</code>
         * method is then called to "render" the cell.  If it is necessary to compute the dimensions of a list because the
         * list cells do not have a fixed size, this method is called to generate a component on which
         * <code>getPreferredSize</code> can be invoked.
         *
         * @param list         The JList we're painting.
         * @param value        The value returned by list.getModel().getElementAt(index).
         * @param index        The cells index.
         * @param isSelected   True if the specified cell was selected.
         * @param cellHasFocus True if the specified cell has the focus.
         * @return A component whose paint() method will render the specified value.
         * @see JList
         * @see ListSelectionModel
         * @see ListModel
         */
        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            if (isSelected){
                setBackground(list.getSelectionBackground());
                setForeground(list.getSelectionForeground());
            } else {
                setBackground(list.getBackground());
                setForeground(list.getForeground());
            }

            if(value != null && value instanceof ServerListConfigurationEntry)
                setText(((ServerListConfigurationEntry) value).getName());
            else
                setText("                                  ");

            return this;
        }
    }

    private class ServerListComboModel extends DefaultComboBoxModel{
        private ServerListManager serverListManager;

        private void refresh(){
            this.removeAllElements();
            //Add the no selection item first then if we have Natives we can add everything else.
            addElement(null);
            if (NativesHelper.isNativeSet()){
                serverListManager = ServerListManagerFactory.getServerListProvider(IdeaPersistenceStoreProvider.INSTANCE);
                Set<ServerListConfigurationEntry> servers  = serverListManager.getServerList().getServers();
                Iterator<ServerListConfigurationEntry> Iterator = servers.iterator();
                while(Iterator.hasNext()){
                    addElement(Iterator.next());
                }
//                for(int i = 0; i < servers.length; i++){
//                    addElement(servers[i]);
//                }
            }
        }
    }

}

